import requests
import json
import time
from datetime import datetime
import logging

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler("dingtalk_forward.log"),
        logging.StreamHandler()
    ]
)


class DingTalkForwarder:
    def __init__(self, app_key, app_secret, source_chat_id, target_chat_id):
        """
        初始化钉钉消息转发器
        :param app_key: 钉钉开放平台应用的AppKey
        :param app_secret: 钉钉开放平台应用的AppSecret
        :param source_chat_id: 源群聊的ChatID (A群)
        :param target_chat_id: 目标群聊的ChatID (B群)
        """
        self.app_key = app_key
        self.app_secret = app_secret
        self.source_chat_id = source_chat_id
        self.target_chat_id = target_chat_id
        self.access_token = None
        self.token_expire_time = 0

    def get_access_token(self):
        """获取访问令牌"""
        # 检查token是否过期
        if self.access_token and time.time() < self.token_expire_time - 300:  # 提前5分钟刷新
            return self.access_token

        url = f"https://oapi.dingtalk.com/gettoken?appkey={self.app_key}&appsecret={self.app_secret}"
        response = requests.get(url)
        result = response.json()

        if result.get("errcode") == 0:
            self.access_token = result.get("access_token")
            self.token_expire_time = time.time() + result.get("expires_in", 7200)
            logging.info("获取access_token成功")
            return self.access_token
        else:
            logging.error(f"获取access_token失败: {result.get('errmsg')}")
            return None

    def get_chat_messages(self, start_time=None, count=20):
        """
        获取群聊消息
        :param start_time: 开始时间戳，默认获取最近的消息
        :param count: 获取消息数量
        :return: 消息列表
        """
        access_token = self.get_access_token()
        if not access_token:
            return []

        url = f"https://oapi.dingtalk.com/chat/getConversationMsg?access_token={access_token}"

        if not start_time:
            # 默认获取最近10分钟的消息
            start_time = int(time.time() - 600)

        params = {
            "chatid": self.source_chat_id,
            "start_time": start_time,
            "count": count,
            "cursor": 0
        }

        try:
            response = requests.post(url, json=params)
            result = response.json()

            if result.get("errcode") == 0:
                logging.info(f"成功获取{len(result.get('messages', []))}条消息")
                return result.get("messages", [])
            else:
                logging.error(f"获取消息失败: {result.get('errmsg')}")
                return []
        except Exception as e:
            logging.error(f"获取消息时发生错误: {str(e)}")
            return []

    def send_message(self, message):
        """
        发送消息到目标群聊
        :param message: 要发送的消息内容
        :return: 发送结果
        """
        access_token = self.get_access_token()
        if not access_token:
            return False

        url = f"https://oapi.dingtalk.com/chat/send?access_token={access_token}"

        # 构建消息体，这里处理文本消息，其他类型消息可以扩展
        msg_content = {
            "msgtype": "text",
            "text": {
                "content": message
            },
            "chatid": self.target_chat_id
        }

        try:
            response = requests.post(url, json=msg_content)
            result = response.json()

            if result.get("errcode") == 0:
                logging.info("消息发送成功")
                return True
            else:
                logging.error(f"消息发送失败: {result.get('errmsg')}")
                return False
        except Exception as e:
            logging.error(f"发送消息时发生错误: {str(e)}")
            return False

    def forward_messages(self, last_processed_time=None):
        """
        转发新消息
        :param last_processed_time: 上次处理的时间戳
        :return: 最新处理的时间戳
        """
        if not last_processed_time:
            # 如果没有上次处理时间，默认从10分钟前开始
            last_processed_time = int(time.time() - 600)

        # 获取新消息
        messages = self.get_chat_messages(start_time=last_processed_time)

        if not messages:
            logging.info("没有新消息需要转发")
            return last_processed_time

        # 记录最新的消息时间
        latest_time = last_processed_time

        # 转发每条消息
        for msg in messages:
            msg_time = msg.get("createAt", 0) / 1000  # 转换为秒
            sender = msg.get("senderNick", "未知发送者")

            # 只处理文本消息，其他类型可以扩展
            if msg.get("msgtype") == "text":
                content = msg.get("text", {}).get("content", "")
                # 添加发送者信息后转发
                forward_content = f"[{sender}] 转发消息: {content}"

                if self.send_message(forward_content):
                    logging.info(f"转发消息成功: {forward_content}")
                    if msg_time > latest_time:
                        latest_time = msg_time

        return latest_time


def main():
    # 配置参数 - 请替换为实际的值
    APP_KEY = "你的AppKey"
    APP_SECRET = "你的AppSecret"
    SOURCE_CHAT_ID = "A群的ChatID"  # 源群聊ID
    TARGET_CHAT_ID = "B群的ChatID"  # 目标群聊ID
    CHECK_INTERVAL = 60  # 检查间隔，单位：秒

    forwarder = DingTalkForwarder(APP_KEY, APP_SECRET, SOURCE_CHAT_ID, TARGET_CHAT_ID)
    last_processed_time = None

    logging.info("钉钉消息转发器启动成功，开始监听消息...")

    try:
        while True:
            last_processed_time = forwarder.forward_messages(last_processed_time)
            time.sleep(CHECK_INTERVAL)
    except KeyboardInterrupt:
        logging.info("用户中断，程序退出")
    except Exception as e:
        logging.error(f"程序发生异常: {str(e)}")


if __name__ == "__main__":
    main()
